package com.smmisia.article.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smmisia.article.entity.Attraction;
import com.smmisia.article.entity.AttractionScenicSpot;
import com.smmisia.article.entity.convetor.AttractionConvertor;
import com.smmisia.article.exception.customException;
import com.smmisia.article.mapper.AttractionScenicSpotMapper;
import com.smmisia.article.request.AttractionCreateRequest;
import com.smmisia.article.request.AttractionUpdateRequest;
import com.smmisia.article.response.AttractionResponse;
import com.smmisia.article.service.AttractionService;
import com.smmisia.article.mapper.AttractionMapper;
import com.smmisia.article.service.ScenicSpotService;
import com.smmisia.common.Result.Result;
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;


@Service
public class AttractionServiceImpl extends ServiceImpl<AttractionMapper, Attraction>
        implements AttractionService, InitializingBean {

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private AttractionScenicSpotMapper attractionScenicSpotMapper;

    @Autowired
    private AttractionMapper attractionMapper;

    private RBloomFilter<String> attractionFilter;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> create(AttractionCreateRequest request) {
        //判断是否重复
        Assert.isTrue(!attractionFilter.contains(request.getAttractName()), () -> new customException("景点已存在"));
        Attraction attraction = Attraction.create(request);
        Assert.isTrue(save(attraction), () -> new customException("创建失败"));
        //添加到景区关联表
        insertAttractionScenicSpot(attraction.getId(), request.getScenicSpotId());
        attractionFilter.add(attraction.getAttractName());
        return Result.ok(true);
    }

    @Override
    public Result<Boolean> updateInfo(AttractionUpdateRequest attractionUpdateRequest) {
        Attraction attraction = attractionMapper.selectOne(Wrappers.lambdaQuery(Attraction.class)
                .eq(Attraction::getId, attractionUpdateRequest.getId())
                .eq(Attraction::getUserId, StpUtil.getLoginIdAsInt()));
        Assert.isTrue(attraction != null, () -> new customException("景点不存在"));
        if(!attraction.getAttractName().equals(attractionUpdateRequest.getAttractName())){
            Assert.isTrue(!attractionFilter.contains(attractionUpdateRequest.getAttractName()), () -> new customException("景点已存在"));
        }
        boolean save = save(Attraction.builder()
                .id(attractionUpdateRequest.getId())
                .attractName(attractionUpdateRequest.getAttractName())
                .description(attractionUpdateRequest.getDescription())
                .position(attractionUpdateRequest.getPosition())
                .images(attractionUpdateRequest.getImages())
                .video(attractionUpdateRequest.getVideo())
                .phone(attractionUpdateRequest.getPhone())
                .address(attractionUpdateRequest.getAddress())
                .startTime(attractionUpdateRequest.getStartTime())
                .endTime(attractionUpdateRequest.getEndTime())
                .tag(attractionUpdateRequest.getTag())
                .build());
        Assert.isTrue(save, () -> new customException("更新失败"));
        return Result.ok(true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> delete(Integer id) {
        Attraction attraction = attractionMapper.selectOne(Wrappers.lambdaQuery(Attraction.class)
                .eq(Attraction::getId, id)
                .eq(Attraction::getUserId, StpUtil.getLoginIdAsInt()));
        Assert.isTrue(attraction != null, () -> new customException("景点不存在"));
        Assert.isTrue(removeById(id), () -> new customException("删除失败"));
        deleteAttractionScenicSpot(id, attraction.getScenicSpotId());
        return Result.ok(true);
    }

    @Override
    public Result<AttractionResponse> info(Integer id) {
        Attraction attraction = attractionMapper.selectById(id);
        Assert.isTrue(attraction != null, () -> new customException("景点不存在"));
        return Result.ok(AttractionConvertor.INSTANCE.toResponse(attraction));
    }

    @Override
    public Result<List<AttractionResponse>> getList(Integer id) {
        List<AttractionScenicSpot> attractionScenicSpots = attractionScenicSpotMapper.selectList(Wrappers.lambdaQuery(AttractionScenicSpot.class)
                .eq(AttractionScenicSpot::getScenicSpotId, id));
        List<Integer> attractionIds = attractionScenicSpots.stream().map(AttractionScenicSpot::getAttractionId).collect(Collectors.toList());
        List<Attraction> attractions = attractionMapper.selectBatchIds(attractionIds);
        return Result.ok(AttractionConvertor.INSTANCE.toResponse(attractions));
    }

    public Boolean insertAttractionScenicSpot(Integer attractionId, Integer scenicSpotId) {
        AttractionScenicSpot attractionScenicSpot = new AttractionScenicSpot();
        attractionScenicSpot.setAttractionId(attractionId);
        attractionScenicSpot.setScenicSpotId(scenicSpotId);
        int insert = attractionScenicSpotMapper.insert(attractionScenicSpot);
        Assert.isTrue(insert == 1, () -> new customException("景区景点关联失败"));
        return true;
    }

    public Boolean deleteAttractionScenicSpot(Integer attractionId, Integer scenicSpotId) {
        int delete = attractionScenicSpotMapper.delete(Wrappers.lambdaQuery(AttractionScenicSpot.class)
                .eq(AttractionScenicSpot::getAttractionId, attractionId)
                .eq(AttractionScenicSpot::getScenicSpotId, scenicSpotId));
        Assert.isTrue(delete == 1, () -> new customException("景区景点关联删除失败"));
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        attractionFilter = redisson.getBloomFilter("attraction");
        attractionFilter.tryInit(1000000, 0.0001);
    }
}




